package com.demo.work.freemarker;

import com.demo.work.freemarker.model.JavaTemplateModel;
import com.sun.deploy.util.StringUtils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.Arrays;
import java.util.stream.Collectors;

/**
 *
 * TODO 使用面向对象的编程思想优化这个类
 * 最常见的问题：
 *     java.io.FileNotFoundException: xxx does not exist. 解决方法：要有耐心
 *     FreeMarker jar 最新的版本（2.3.23）提示 Configuration 方法被弃用
 * 代码自动生产基本原理：
 *     数据填充 freeMarker 占位符
 * @author 19042980
 */
@Data
@Slf4j
@Accessors(chain = true)
public class FreeMarkerHelper {

    private String sourceDir;
    private String templateModule;
    private String templatePackage;
    private String outputRootPath;
    private String outputBasePackage;
    private String outputModule;

    private Configuration configuration;

    public void init(){
        if (this.sourceDir == null){
            this.sourceDir = unionToPath("src", "main", "java");
        }
        configuration = new Configuration();
        try {
            configuration.setDirectoryForTemplateLoading(new File(this.getTemplatePath()));
        } catch (IOException e) {
            throw new RuntimeException("文件IO异常，请检查模板文件路径是否正确");
        }
    }

    public void generate(JavaTemplateModel dataModel){
        Writer out = null;
        try {
            Template template = configuration.getTemplate(dataModel.getTemplateFileName());
            String outputFileName = dataModel.getOutputName();

            File docFile = new File(getOutputPath(outputFileName));
            boolean mkdirs = docFile.getParentFile().mkdir();
            if (mkdirs){
                log.info("目录不存在，创建目录 {}", docFile.getParent());
            }
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
            template.process(dataModel, out);
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }finally {
            try {
                if (null != out) {
                    out.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }

    private String getTemplatePath() {
        return unionToPath(outputModule, sourceDir, packageToPath(outputBasePackage), packageToPath(templatePackage));
    }

    private String getOutputPath(String fileName) {
        return unionToPath(outputRootPath, outputModule, sourceDir, packageToPath(outputBasePackage), fileName);
    }

    private String packageToPath(String packageStr){
        if (isEmpty(packageStr)){
            return "";
        }else {
            return packageStr.replace(".", File.separator);
        }
    }

    /**
     * 把参数拼接成路径，包路径替换成系统文件路径
     * @param paths
     * @return
     */
    private String unionToPath(String... paths){
        return StringUtils.join(Arrays.stream(paths).filter(e -> !isEmpty(e)).peek(this::packageToPath).collect(Collectors.toList()), File.separator);
    }

    private boolean isEmpty(String str){
        return str == null || str.isEmpty();
    }

}